package com.sangmo.boot.auth.core.filter;

import com.sangmo.boot.auth.core.AuthorizeService;
import com.sangmo.boot.auth.core.interfaces.ValidateTokenRequest;
import com.sangmo.boot.framework.api.utils.ApiResponse;
import com.sangmo.boot.framework.common.errors.ServiceException;
import com.sangmo.boot.framework.common.errors.StandardErrors;
import com.sangmo.boot.framework.common.i18n.MessageMaker;
import com.sangmo.boot.framework.common.session.UserSession;
import com.sangmo.boot.framework.common.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class DefaultAuthorizeFilter implements Filter {
    private static Logger LOG = LoggerFactory.getLogger(DefaultAuthorizeFilter.class);

    private String clientId;
    private String resourceId;
    private String scope;
    @Autowired
    private AuthorizeService authorizeService;

    @Autowired
    private MessageMaker messageMaker;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        final String accessToken = httpRequest.getParameter("access_token");
        try {
            UserSession.setAuthorize(null);
            ValidateTokenRequest validateTokenRequest = new ValidateTokenRequest();
            validateTokenRequest.setClientId(clientId);
            validateTokenRequest.setAccessToken(accessToken);

            UserSession.Authorize<?> auth = authorizeService.validate(validateTokenRequest);

            if (null == auth) {
                throw new ServiceException(StandardErrors.AUTHORIZED_WRONG.getStatus(), "error.auth.authorize.invalid", accessToken);
            }
            else {
                this.checkAuthorize(auth);
                UserSession.setAuthorize(auth);
            }
        }
        catch (ServiceException se) {
            String message = messageMaker.make(se.getKey(), se.getParams());
            ApiResponse resp = ApiResponse.make(se.getStatus(), message);
            response.getWriter().write(JsonUtils.writeValue(resp));
            response.getWriter().flush();
            return;
        }
        catch (Exception ex) {
            String message = messageMaker.make("error.auth.authorize");
            LOG.error(message, ex);
            ApiResponse resp = ApiResponse.make(StandardErrors.UNAUTHORIZED.getStatus(), message, null);
            response.getWriter().write(JsonUtils.writeValue(resp));
            response.getWriter().flush();
            return;
        }
        filterChain.doFilter(request, response);
    }

    protected void checkAuthorize(UserSession.Authorize<?> auth) {

    }

    public String getResourceId() {
        return resourceId;
    }

    public void setResourceId(String resourceId) {
        this.resourceId = resourceId;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }
}
